package org.jader.bolao.gui.swing;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import org.jader.bolao.Championship;
import org.jader.bolao.Player;
import org.jader.bolao.Team;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.FilterPipeline;
import org.jdesktop.swingx.decorator.PatternFilter;
import org.jdesktop.swingx.decorator.SortOrder;

public class SelectPlayerDialog extends JDialog {
	private static final long serialVersionUID = 1L;

	private Championship championship = null;
	private boolean okClicked = false;
	
	private JPanel jContentPane = null;
	private JPanel northPanel = null;
	private JLabel playersLabel = null;
	private JPanel buttonsPanel = null;
	private JButton okButton = null;
	private JButton cancelButton = null;
	private JPanel tablePanel = null;
	private JScrollPane tableScrollPane = null;
	private JXTable playersTable = null;
	private JPanel labelPanel = null;
	private JPanel filterPanel = null;
	private JLabel searchLabel = null;
	private JTextField searchTextField = null;

	/**
	 * @param owner
	 */
	public SelectPlayerDialog(Frame application, Championship c) {
		super(application);
		this.championship = c;
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(517, 395);
		this.setLocationRelativeTo(this.getParent());
		this.setTitle("Selecionar jogador");
		this.setModalityType(ModalityType.APPLICATION_MODAL);
		this.setContentPane(getJContentPane());
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getNorthPanel(), BorderLayout.NORTH);
			jContentPane.add(getButtonsPanel(), BorderLayout.SOUTH);
			jContentPane.add(getTablePanel(), BorderLayout.CENTER);
		}
		return jContentPane;
	}

	/**
	 * This method initializes northPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getNorthPanel() {
		if (northPanel == null) {
			playersLabel = new JLabel();
			playersLabel.setText("Jogadores");
			northPanel = new JPanel();
			northPanel.setLayout(new BoxLayout(getNorthPanel(), BoxLayout.Y_AXIS));
			northPanel.add(getLabelPanel(), null);
			northPanel.add(getFilterPanel(), null);
		}
		return northPanel;
	}

	/**
	 * This method initializes buttonsPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getButtonsPanel() {
		if (buttonsPanel == null) {
			FlowLayout flowLayout1 = new FlowLayout();
			flowLayout1.setAlignment(FlowLayout.CENTER);
			buttonsPanel = new JPanel();
			buttonsPanel.setLayout(flowLayout1);
			buttonsPanel.add(getOkButton(), null);
			buttonsPanel.add(getCancelButton(), null);
		}
		return buttonsPanel;
	}

	/**
	 * This method initializes okButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getOkButton() {
		if (okButton == null) {
			okButton = new JButton();
			okButton.setText("OK");
			okButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					okClicked();
				}
			});
		}
		return okButton;
	}
	
	private void okClicked() {
		if (getPlayersTable().getRowCount() == 1) {
			// If only one row is being displayed, select it automatically
			getPlayersTable().setRowSelectionInterval(0, 0);
		}
		if (getPlayersTable().getSelectedRowCount() == 0) {
			JOptionPane.showMessageDialog(this, "Selecione o jogador desejado.", "Selecionar jogador", JOptionPane.WARNING_MESSAGE);
		}
		okClicked = true;
		dispose();
	}

	/**
	 * This method initializes cancelButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getCancelButton() {
		if (cancelButton == null) {
			cancelButton = new JButton();
			cancelButton.setText("Cancel");
			cancelButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					dispose();
				}
			});
		}
		return cancelButton;
	}

	/**
	 * This method initializes tablePanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getTablePanel() {
		if (tablePanel == null) {
			tablePanel = new JPanel();
			tablePanel.setLayout(new FlowLayout());
			tablePanel.add(getTableScrollPane(), null);
		}
		return tablePanel;
	}

	/**
	 * This method initializes tableScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getTableScrollPane() {
		if (tableScrollPane == null) {
			tableScrollPane = new JScrollPane();
			tableScrollPane.setPreferredSize(new Dimension(453, 250));
			tableScrollPane.setViewportView(getPlayersTable());
		}
		return tableScrollPane;
	}

	/**
	 * This method initializes playersTable	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JXTable getPlayersTable() {
		if (playersTable == null) {
			playersTable = new JXTable(new PlayersTableModel(championship));
			playersTable.setSortOrder(0, SortOrder.ASCENDING);
			playersTable.setColumnControlVisible(true);
			playersTable.addMouseListener(new MouseListener() {
				@Override
				public void mouseClicked(MouseEvent me) {
					if (me.getClickCount() > 1) {
						okClicked();
					}
				}

				@Override
				public void mouseEntered(MouseEvent arg0) {}

				@Override
				public void mouseExited(MouseEvent arg0) {}

				@Override
				public void mousePressed(MouseEvent arg0) {}

				@Override
				public void mouseReleased(MouseEvent arg0) {}
			});
		}
		return playersTable;
	}

	public Player getSelectedPlayer() {
		if (okClicked) {
			int row = getPlayersTable().getSelectedRow();
			if (row > -1 && row < getPlayersTable().getModel().getRowCount()) {
				return (Player) getPlayersTable().getValueAt(row, 0);
			}
		}
		return null;
	}

	/**
	 * This method initializes labelPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getLabelPanel() {
		if (labelPanel == null) {
			FlowLayout flowLayout = new FlowLayout();
			flowLayout.setAlignment(FlowLayout.LEFT);
			labelPanel = new JPanel();
			labelPanel.setLayout(flowLayout);
			labelPanel.add(playersLabel, null);
		}
		return labelPanel;
	}

	/**
	 * This method initializes filterPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getFilterPanel() {
		if (filterPanel == null) {
			searchLabel = new JLabel();
			searchLabel.setText("Search: ");
			filterPanel = new JPanel();
			filterPanel.setLayout(new FlowLayout());
			filterPanel.add(searchLabel, null);
			filterPanel.add(getSearchTextField(), null);
		}
		return filterPanel;
	}

	/**
	 * This method initializes searchTextField	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getSearchTextField() {
		if (searchTextField == null) {
			searchTextField = new JTextField();
			searchTextField.setColumns(20);
			searchTextField.addKeyListener(new KeyListener() {
				@Override
				public void keyPressed(KeyEvent arg0) {
					refreshFilter();
				}

				@Override
				public void keyReleased(KeyEvent arg0) {
					refreshFilter();
				}

				@Override
				public void keyTyped(KeyEvent arg0) {
					if (arg0.getKeyChar() == KeyEvent.VK_ENTER) {
						if (getPlayersTable().getRowCount() == 1)
							okClicked();
					}
					else
						refreshFilter();
				}
			});
		}
		return searchTextField;
	}
	
	private void refreshFilter() {
		getPlayersTable().setFilters(new FilterPipeline(new PatternFilter(getSearchTextField().getText(), Pattern.CASE_INSENSITIVE, 0)));
	}
	
	private class PlayersTableModel extends DefaultTableModel {
		private static final long serialVersionUID = 1L;
		
		private Championship championship = null;
		private List<Player> players = new LinkedList<Player>();
		private final String[] COLUMNS = {"Nome", "Modalidade", "Sociedade"};
		
		private PlayersTableModel(Championship c) {
			this.championship = c;
			loadPlayers();
		}

		private void loadPlayers() {
			Iterator<Team> itt = championship.teamsIterator();
			while (itt.hasNext()) {
				Iterator<Player> itp = itt.next().playerIterator();
				while (itp.hasNext()) {
					players.add(itp.next());
				}
			}
		}

		@Override
		public int getColumnCount() {
			return COLUMNS.length;
		}

		@Override
		public String getColumnName(int column) {
			return COLUMNS[column];
		}

		@Override
		public int getRowCount() {
			if (players == null) return 0;
			return players.size();
		}

		@Override
		public Object getValueAt(int row, int column) {
			Player p = players.get(row);
			switch (column) {
			case 0:
				return p;
			case 1:
				return p.getModality();
			case 2:
				return p.team();
			}
			return null;
		}

		@Override
		public boolean isCellEditable(int arg0, int arg1) {
			return false;
		}
	}

}  //  @jve:decl-index=0:visual-constraint="10,10"
